<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title>Parse Excerpts</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
		<meta name="viewport" content="width=device-width initial-scale=1">
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta http-equiv="Content-Language" content="en-gb">

<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
  var popup = document.getElementById(material_id);
  popup.classList.toggle("show");
}
</script>

<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
		
	</head>
	<body class="commentary-font">
		<nav role="navigation">
		<h1><a href="../index.html"><img src="../docs-assets/Inform.png" height=72> </a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=0> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=0> inweb</a></li>
<li><a href="https://github.com/ganelson/intest"><img src="../docs-assets/github.png" height=0> intest</a></li>
</ul>
		</nav>
		<main role="main">
		<!-- Weave of 'Parse Excerpts' generated by inweb -->
<div class="breadcrumbs">
    <ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../services.html">Services</a></li><li><a href="index.html">lexicon</a></li><li><a href="index.html#2">Chapter 2: Excerpts</a></li><li><b>Parse Excerpts</b></li></ul></div>
<p class="purpose">Given an excerpt of wording, to construct S-nodes for one or more registered excerpt meanings which it matches.</p>

<ul class="toc"><li><a href="2-pe.html#SP1">&#167;1. Default bitmaps</a></li><li><a href="2-pe.html#SP2">&#167;2. Parsing methods</a></li><li><a href="2-pe.html#SP5_4">&#167;5.4. Exact parsing mode</a></li><li><a href="2-pe.html#SP5_5">&#167;5.5. Maximal parsing mode</a></li><li><a href="2-pe.html#SP5_6">&#167;5.6. Parametrised parsing mode</a></li><li><a href="2-pe.html#SP5_7">&#167;5.7. Subset parsing mode</a></li><li><a href="2-pe.html#SP9">&#167;9. Monitoring the efficiency of the parser</a></li></ul><hr class="tocbar">

<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Default bitmaps.</b>The following will be useful only for minimal use of <a href="index.html" class="internal">lexicon</a>. Inform
certainly doesn't use settings as minimal as these &mdash; see
<a href="../values-module/1-mc.html" class="internal">Meaning Codes (in values)</a> for what it does do.
</p>

<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">ONE_WEIRD_TRICK_DISCOVERED_BY_A_MOM_MC</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00000004</span><span class="plain-syntax"> </span><span class="comment-syntax"> meaningless, so do not use</span>
<span class="definition-keyword">default</span> <span class="constant-syntax">EXACT_PARSING_BITMAP</span>
<span class="plain-syntax">    (</span><span class="identifier-syntax">MISCELLANEOUS_MC</span><span class="plain-syntax">)</span>
<span class="definition-keyword">default</span> <span class="constant-syntax">SUBSET_PARSING_BITMAP</span>
<span class="plain-syntax">    (</span><span class="identifier-syntax">NOUN_MC</span><span class="plain-syntax">)</span>
<span class="definition-keyword">default</span> <span class="constant-syntax">PARAMETRISED_PARSING_BITMAP</span>
<span class="plain-syntax">    (</span><span class="constant-syntax">ONE_WEIRD_TRICK_DISCOVERED_BY_A_MOM_MC</span><span class="plain-syntax">)</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. Parsing methods.</b>The excerpt parser tests a given wording to see if it matches something
in the bank of excerpt meanings. It looks only for atomic meanings ("box"):
more sophisticated grammar higher up will have to parse compound meanings
(such as "something in an open box").
</p>

<p class="commentary">We will return either a single result or a list of possible results, as
alternative readings. It is not at all easy to decide what "door"
means, for instance: the class of doors, or a particular door, and if so
then which one? We cannot answer that question here, and do not even try.
However, we can specify a context, in effect saying something like "what
would this mean if it had to be an adjective name?".
</p>

<p class="commentary">Depending on that context, four basic parsing modes can then be used.
</p>

<ul class="items"><li>(1) Exact parsing is what it sounds like: the texts have to match exactly,
except that an initial article is skipped. Thus "the going action"
exactly matches "going action", but "going" does not.
</li><li>(2) In subset parsing, a match is achieved if the text parsed consists of
words all of which are found in the meaning tested. Thus "red door" and
"red" are each subset matches for "ornate red door with brass handle".
</li><li>(3) In parametrised parsing, arbitrary (non-empty) text is allowed to
match against <span class="extract"><span class="extract-syntax">#</span></span> gaps in the token list. Thus "award 5 points" is a
parametrised match for "award <span class="extract"><span class="extract-syntax">#</span></span> points".
</li><li>(4) In maximal parsing, we find the longest possible initial match, allowing
it even if it does reach to the end of the excerpt, and we return a unique
finding, not a list of possibilities.
</li></ul>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">EXACT_PM</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">SUBSET_PM</span><span class="plain-syntax"> </span><span class="constant-syntax">2</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">PARAMETRISED_PM</span><span class="plain-syntax"> </span><span class="constant-syntax">4</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">MAXIMAL_PM</span><span class="plain-syntax"> </span><span class="constant-syntax">8</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b>To monitor the efficiency of the excerpt parser, we keep track of:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_calls_to_parse_excerpt</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">,</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">no_meanings_tried</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">,</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">no_meanings_tried_in_detail</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">,</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">no_successful_calls_to_parse_excerpt</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">no_matched_ems</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>In addition, it turns out to be convenient to have a global mode, for the
sake of disambiguating awkward cases:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">word_to_suppress_in_phrases</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. </b>As input, we supply not just the excerpt but also a context; or, to put it
another way, a filter on which excerpt meanings to look at. This must be a
bitmap made up from meaning codes, such as <span class="extract"><span class="extract-syntax">TABLE_MC + TABLE_COLUMN_MC</span></span>,
which would check for tables and table columns simultaneously.
</p>

<p class="commentary">However, there is one restriction on this. Recall that there are four
parsing modes, and that different modes are used for different meaning
codes. The <span class="extract"><span class="extract-syntax">mc_bitmap</span></span> context is required not to mix MCs with different
parsing modes.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="function-syntax">FromLexicon::parse</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">FromLexicon::parse</span></span>:<br/>Lexicon - <a href="1-lxc.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">mc_bitmap</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">results</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">no_calls_to_parse_excerpt</span><span class="plain-syntax">++;</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::empty</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::paired_brackets</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Wordings::trim_both_ends</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::empty</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">parsing_mode</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">hash</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_1" class="named-paragraph-link"><span class="named-paragraph">Choose which parsing mode we should use, given the MC bitmap</span><span class="named-paragraph-number">5.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_2" class="named-paragraph-link"><span class="named-paragraph">Take note of casing on first word, in the few circumstances when we care</span><span class="named-paragraph-number">5.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_3" class="named-paragraph-link"><span class="named-paragraph">Skip an initial article most of the time</span><span class="named-paragraph-number">5.3</span></a></span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">hash</span><span class="plain-syntax"> = </span><span class="identifier-syntax">hash</span><span class="plain-syntax"> | </span><a href="2-em.html#SP8" class="function-link"><span class="function-syntax">ExcerptMeanings::hash_code</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">EXCERPT_PARSING</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="string-syntax">"Parsing excerpt &lt;%W&gt; hash %08x mc $N mode %d\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">hash</span><span class="plain-syntax">, </span><span class="identifier-syntax">mc_bitmap</span><span class="plain-syntax">, </span><span class="identifier-syntax">parsing_mode</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><span class="identifier-syntax">parsing_mode</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">EXACT_PM:</span><span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_4" class="named-paragraph-link"><span class="named-paragraph">Enter exact parsing mode</span><span class="named-paragraph-number">5.4</span></a></span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">MAXIMAL_PM:</span><span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_5" class="named-paragraph-link"><span class="named-paragraph">Enter maximal parsing mode</span><span class="named-paragraph-number">5.5</span></a></span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">PARAMETRISED_PM:</span><span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_6" class="named-paragraph-link"><span class="named-paragraph">Enter parametrised parsing mode</span><span class="named-paragraph-number">5.6</span></a></span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">SUBSET_PM:</span><span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_7" class="named-paragraph-link"><span class="named-paragraph">Enter subset parsing mode</span><span class="named-paragraph-number">5.7</span></a></span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">: </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"mc_bitmap: $N\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">mc_bitmap</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Unknown parsing mode"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">default:</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"pm: %08x mc_bitmap: $N\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">parsing_mode</span><span class="plain-syntax">, </span><span class="identifier-syntax">mc_bitmap</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Mixed parsing modes"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">EXCERPT_PARSING</span><span class="plain-syntax">, </span><span class="string-syntax">"Completed:\n$m"</span><span class="plain-syntax">, </span><span class="identifier-syntax">results</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">results</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">loopy</span><span class="plain-syntax"> = </span><span class="identifier-syntax">results</span><span class="plain-syntax">; </span><span class="identifier-syntax">loopy</span><span class="plain-syntax">; </span><span class="identifier-syntax">loopy</span><span class="plain-syntax"> = </span><span class="identifier-syntax">loopy</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax">)</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">no_matched_ems</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">no_successful_calls_to_parse_excerpt</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">results</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5_1" class="paragraph-anchor"></a><b>&#167;5.1. </b>Maximal parsing is something of a special case: it is used only for adjective
lists, and we can only enter that mode by calling with exactly the correct
bitmap for this. Otherwise, the parsing mode depends on which MC(s) are
included in the bitmap.
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Choose which parsing mode we should use, given the MC bitmap</span><span class="named-paragraph-number">5.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">parsing_mode</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">mc_bitmap</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">EXACT_PARSING_BITMAP</span><span class="plain-syntax">) </span><span class="identifier-syntax">parsing_mode</span><span class="plain-syntax"> |= </span><span class="constant-syntax">EXACT_PM</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">mc_bitmap</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">SUBSET_PARSING_BITMAP</span><span class="plain-syntax">) </span><span class="identifier-syntax">parsing_mode</span><span class="plain-syntax"> |= </span><span class="constant-syntax">SUBSET_PM</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">mc_bitmap</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">PARAMETRISED_PARSING_BITMAP</span><span class="plain-syntax">) </span><span class="identifier-syntax">parsing_mode</span><span class="plain-syntax"> |= </span><span class="constant-syntax">PARAMETRISED_PM</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">lexicon_in_maximal_mode</span><span class="plain-syntax">) </span><span class="identifier-syntax">parsing_mode</span><span class="plain-syntax"> = </span><span class="constant-syntax">MAXIMAL_PM</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5">&#167;5</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_2" class="paragraph-anchor"></a><b>&#167;5.2. </b>Recall that excerpt parsing is case insensitive except for the first word
of a text substitution, and then only when two definitions have been given,
one capitalising the word and the other not, or when the word is a single
letter long.
</p>

<p class="commentary">If we find the upper case form of such a text substitution, we set a special
bit in the hash code. (The upper and lower case forms are both registered as
excerpt meanings, with the same hash code except that one has this extra bit
set and the other hasn't.)
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Take note of casing on first word, in the few circumstances when we care</span><span class="named-paragraph-number">5.2</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">EM_CASE_SENSITIVITY_TEST_LEXICON_CALLBACK</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">EM_CASE_SENSITIVITY_TEST_LEXICON_CALLBACK</span><span class="plain-syntax">(</span><span class="identifier-syntax">mc_bitmap</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">inchar32_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tx</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lexer::word_raw_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">));</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">tx</span><span class="plain-syntax">[0]) &amp;&amp; (</span><span class="identifier-syntax">Characters::isupper</span><span class="plain-syntax">(</span><span class="identifier-syntax">tx</span><span class="plain-syntax">[0])) &amp;&amp;</span>
<span class="plain-syntax">            ((</span><span class="identifier-syntax">tx</span><span class="plain-syntax">[1] == </span><span class="constant-syntax">0</span><span class="plain-syntax">) ||</span>
<span class="plain-syntax">                (</span><span class="identifier-syntax">Vocabulary::used_case_sensitively</span><span class="plain-syntax">(</span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)))))) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">hash</span><span class="plain-syntax"> = </span><span class="identifier-syntax">hash</span><span class="plain-syntax"> | </span><span class="constant-syntax">CAPITALISED_VARIANT_FORM</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5">&#167;5</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_3" class="paragraph-anchor"></a><b>&#167;5.3. </b>An initial article is always skipped unless we are looking at a phrase;
but then we are only allowed to skip an initial "the", and even then only
if we aren't looking for text substitutions.
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Skip an initial article most of the time</span><span class="named-paragraph-number">5.3</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">parsing_mode</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">PARAMETRISED_PM</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">EM_IGNORE_DEFINITE_ARTICLE_TEST_LEXICON_CALLBACK</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">EM_IGNORE_DEFINITE_ARTICLE_TEST_LEXICON_CALLBACK</span><span class="plain-syntax">(</span><span class="identifier-syntax">mc_bitmap</span><span class="plain-syntax">))</span>
<span class="plain-syntax">        #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Articles::remove_the</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Articles::remove_article</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5">&#167;5</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. </b>When checking cases below, we are always going to consider only those
which have a meaning code among those we are looking for:
</p>

<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="identifier-syntax">EXCERPT_MEANING_RELEVANT</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)</span>
<span class="plain-syntax">    (</span><span class="identifier-syntax">no_meanings_tried</span><span class="plain-syntax">++, ((</span><span class="identifier-syntax">mc_bitmap</span><span class="plain-syntax"> &amp; (</span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">meaning_code</span><span class="plain-syntax">))!=0))</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">EXAMINE_EXCERPT_MEANING_IN_DETAIL</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">EXCERPT_PARSING</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="string-syntax">"Trying $M (parsing mode %d)\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">), </span><span class="identifier-syntax">parsing_mode</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">no_meanings_tried_in_detail</span><span class="plain-syntax">++;</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5_4" class="paragraph-anchor"></a><b>&#167;5.4. Exact parsing mode.</b>Exact matching is just what it sounds like: the match must be word
for word. Because of that, the excerpt meaning is guaranteed to be listed
under the start list of the first word, if it matches (because there cannot
be <span class="extract"><span class="extract-syntax">#</span></span> tokens in the token list &mdash; if there were, we would be in parametrised
parsing mode).
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Enter exact parsing mode</span><span class="named-paragraph-number">5.4</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">v</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">));</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">v</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Unidentified word when parsing"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">v</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">flags</span><span class="plain-syntax">) &amp; </span><span class="identifier-syntax">mc_bitmap</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">v</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">means</span><span class="plain-syntax">.</span><span class="element-syntax">start_list</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax">)</span>
<span class="plain-syntax">            </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_4_1" class="named-paragraph-link"><span class="named-paragraph">Try to match excerpt in exact parsing mode</span><span class="named-paragraph-number">5.4.1</span></a></span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5">&#167;5</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_4_1" class="paragraph-anchor"></a><b>&#167;5.4.1. </b>In exact parsing, the hash codes must agree perfectly:
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Try to match excerpt in exact parsing mode</span><span class="named-paragraph-number">5.4.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">EXCERPT_MEANING_RELEVANT</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">hash</span><span class="plain-syntax"> == </span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">excerpt_hash</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="constant-syntax">EXAMINE_EXCERPT_MEANING_IN_DETAIL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">no_em_tokens</span><span class="plain-syntax"> == </span><span class="identifier-syntax">Wordings::length</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">j</span><span class="plain-syntax">, </span><span class="identifier-syntax">k</span><span class="plain-syntax">, </span><span class="identifier-syntax">err</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">j</span><span class="plain-syntax">=0, </span><span class="identifier-syntax">k</span><span class="plain-syntax">=</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">), </span><span class="identifier-syntax">err</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">j</span><span class="function-syntax">&lt;Node::get_meaning(p)-&gt;</span><span class="element-syntax">no_em_tokens</span><span class="plain-syntax">; </span><span class="identifier-syntax">j</span><span class="plain-syntax">++, </span><span class="identifier-syntax">k</span><span class="plain-syntax">++)</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">em_tokens</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">] != </span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">k</span><span class="plain-syntax">)) { </span><span class="identifier-syntax">err</span><span class="plain-syntax">=</span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">; }</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">err</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">results</span><span class="plain-syntax"> = </span><a href="2-pe.html#SP8" class="function-link"><span class="function-syntax">FromLexicon::result</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">), </span><span class="constant-syntax">1</span><span class="plain-syntax">, </span><span class="identifier-syntax">results</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5_4">&#167;5.4</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_5" class="paragraph-anchor"></a><b>&#167;5.5. Maximal parsing mode.</b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Enter maximal parsing mode</span><span class="named-paragraph-number">5.5</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">v</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">));</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">v</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Unidentified word when parsing"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">v</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">flags</span><span class="plain-syntax">) &amp; </span><span class="identifier-syntax">mc_bitmap</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">, *</span><span class="identifier-syntax">best_p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">best_score</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">v</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">means</span><span class="plain-syntax">.</span><span class="element-syntax">start_list</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax">)</span>
<span class="plain-syntax">            </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_5_1" class="named-paragraph-link"><span class="named-paragraph">Try to match excerpt in maximal parsing mode</span><span class="named-paragraph-number">5.5.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">best_p</span><span class="plain-syntax">)</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">results</span><span class="plain-syntax"> =</span>
<span class="plain-syntax">                </span><a href="2-pe.html#SP8" class="function-link"><span class="function-syntax">FromLexicon::result</span></a><span class="plain-syntax">(</span>
<span class="plain-syntax">                    </span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">best_p</span><span class="plain-syntax">), </span><span class="identifier-syntax">best_score</span><span class="plain-syntax">, </span><span class="identifier-syntax">results</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5">&#167;5</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_5_1" class="paragraph-anchor"></a><b>&#167;5.5.1. </b>In maximal matching, we keep only the longest exact match found, and
if two have equal length then keep the first one found. (It should ideally
never be the case that clashes occur.)
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Try to match excerpt in maximal parsing mode</span><span class="named-paragraph-number">5.5.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">EXCERPT_MEANING_RELEVANT</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax">        ((</span><span class="identifier-syntax">hash</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">excerpt_hash</span><span class="plain-syntax">) == </span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">excerpt_hash</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="constant-syntax">EXAMINE_EXCERPT_MEANING_IN_DETAIL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">no_em_tokens</span><span class="plain-syntax"> &lt;= </span><span class="identifier-syntax">Wordings::length</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">j</span><span class="plain-syntax">, </span><span class="identifier-syntax">k</span><span class="plain-syntax">, </span><span class="identifier-syntax">err</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">err</span><span class="plain-syntax">=</span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">, </span><span class="identifier-syntax">j</span><span class="plain-syntax">=0, </span><span class="identifier-syntax">k</span><span class="plain-syntax">=</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">j</span><span class="function-syntax">&lt;Node::get_meaning(p)-&gt;</span><span class="element-syntax">no_em_tokens</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">j</span><span class="plain-syntax">++, </span><span class="identifier-syntax">k</span><span class="plain-syntax">++)</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">em_tokens</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">] != </span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">k</span><span class="plain-syntax">)) { </span><span class="identifier-syntax">err</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">; }</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">err</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">j</span><span class="plain-syntax">&gt;</span><span class="identifier-syntax">best_score</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">best_p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">; </span><span class="identifier-syntax">best_score</span><span class="plain-syntax"> = </span><span class="identifier-syntax">j</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            }</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5_5">&#167;5.5</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_6" class="paragraph-anchor"></a><b>&#167;5.6. Parametrised parsing mode.</b>This is the only parsing mode which allows for arbitrary text to appear:
i.e., where any text X can appear in "award X points", for example.
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Enter parametrised parsing mode</span><span class="named-paragraph-number">5.6</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">v</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">));</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">v</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Unidentified word when parsing"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">EM_ALLOW_BLANK_TEST_LEXICON_CALLBACK</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">EM_ALLOW_BLANK_TEST_LEXICON_CALLBACK</span><span class="plain-syntax">(</span><span class="identifier-syntax">mc_bitmap</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">blank_says_p</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">this_result</span><span class="plain-syntax"> =</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">Node::new_with_words</span><span class="plain-syntax">(</span><span class="identifier-syntax">mc_bitmap</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">SW</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::get_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">this_result</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Node::copy</span><span class="plain-syntax">(</span><span class="identifier-syntax">this_result</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Node::set_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">this_result</span><span class="plain-syntax">, </span><span class="identifier-syntax">SW</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">this_result</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::new_with_words</span><span class="plain-syntax">(</span><span class="identifier-syntax">UNKNOWN_NT</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">this_result</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax"> = </span><span class="identifier-syntax">results</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">results</span><span class="plain-syntax"> = </span><span class="identifier-syntax">this_result</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">no_meanings_tried</span><span class="plain-syntax">++, </span><span class="identifier-syntax">no_meanings_tried_in_detail</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">v</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">means</span><span class="plain-syntax">.</span><span class="element-syntax">start_list</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_6_1" class="named-paragraph-link"><span class="named-paragraph">Try to match excerpt in parametrised parsing mode</span><span class="named-paragraph-number">5.6.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::length</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">) &gt; </span><span class="constant-syntax">1</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">v</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::last_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">));</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">v</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Unidentified word when parsing"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">v</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">means</span><span class="plain-syntax">.</span><span class="element-syntax">end_list</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax">)</span>
<span class="plain-syntax">            </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_6_1" class="named-paragraph-link"><span class="named-paragraph">Try to match excerpt in parametrised parsing mode</span><span class="named-paragraph-number">5.6.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_THROUGH_WORDING</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">v</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">v</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Unidentified word when parsing"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">v</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">means</span><span class="plain-syntax">.</span><span class="element-syntax">middle_list</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax">)</span>
<span class="plain-syntax">                </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_6_1" class="named-paragraph-link"><span class="named-paragraph">Try to match excerpt in parametrised parsing mode</span><span class="named-paragraph-number">5.6.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5">&#167;5</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_6_1" class="paragraph-anchor"></a><b>&#167;5.6.1. </b>It is required here that the data supplied must be a pointer to a phrase,
though it can be any type of phrase.
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Try to match excerpt in parametrised parsing mode</span><span class="named-paragraph-number">5.6.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">eh</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">excerpt_hash</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">EXCERPT_MEANING_RELEVANT</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax">        ((</span><span class="identifier-syntax">hash</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">eh</span><span class="plain-syntax">) == </span><span class="identifier-syntax">eh</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax">        ((</span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">em_tokens</span><span class="plain-syntax">[0] == </span><span class="constant-syntax">0</span><span class="plain-syntax">) ||</span>
<span class="plain-syntax">            ((</span><span class="identifier-syntax">hash</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">CAPITALISED_VARIANT_FORM</span><span class="plain-syntax">) == (</span><span class="identifier-syntax">eh</span><span class="plain-syntax"> &amp; </span><span class="constant-syntax">CAPITALISED_VARIANT_FORM</span><span class="plain-syntax">)))) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_tokens_to_match</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">no_em_tokens</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">saved_W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">W</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">params_W</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_TOKENS_PER_EXCERPT_MEANING</span><span class="plain-syntax">];</span>
<span class="plain-syntax">        #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">ph_opt_W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">EMPTY_WORDING</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">bl</span><span class="plain-syntax">; </span><span class="comment-syntax"> the "bracket level" (0 for unbracketed, 1 for inside one pair, etc.)</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">j</span><span class="plain-syntax">, </span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">err</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="constant-syntax">EXAMINE_EXCERPT_MEANING_IN_DETAIL</span><span class="plain-syntax">;</span>

<span class="plain-syntax">        </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_6_1_1" class="named-paragraph-link"><span class="named-paragraph">Look through to see if there are phrase options at the end</span><span class="named-paragraph-number">5.6.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">err</span><span class="plain-syntax">=</span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">, </span><span class="identifier-syntax">j</span><span class="plain-syntax">=0, </span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">=</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">), </span><span class="identifier-syntax">t</span><span class="plain-syntax">=0, </span><span class="identifier-syntax">bl</span><span class="plain-syntax">=0;</span>
<span class="plain-syntax">            (</span><span class="identifier-syntax">j</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">no_tokens_to_match</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">&lt;=</span><span class="identifier-syntax">Wordings::last_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)); </span><span class="identifier-syntax">j</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">EXCERPT_PARSING</span><span class="plain-syntax">, </span><span class="string-syntax">"j=%d, scan_pos=%d, t=%d\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">j</span><span class="plain-syntax">, </span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">this_word</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">em_tokens</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">];</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">this_word</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_6_1_2" class="named-paragraph-link"><span class="named-paragraph">We're required to match a fixed word</span><span class="named-paragraph-number">5.6.1.2</span></a></span>
<span class="plain-syntax">            </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">j</span><span class="plain-syntax"> == </span><span class="identifier-syntax">no_tokens_to_match</span><span class="plain-syntax">-1)</span>
<span class="plain-syntax">                </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_6_1_3" class="named-paragraph-link"><span class="named-paragraph">We're required to match a parameter at the excerpt's end</span><span class="named-paragraph-number">5.6.1.3</span></a></span>
<span class="plain-syntax">            </span><span class="reserved-syntax">else</span>
<span class="plain-syntax">                </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_6_1_4" class="named-paragraph-link"><span class="named-paragraph">We're required to match a parameter before the excerpt's end</span><span class="named-paragraph-number">5.6.1.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">EXCERPT_PARSING</span><span class="plain-syntax">, </span><span class="string-syntax">"outcome has err=%d (hash here %08x)\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">err</span><span class="plain-syntax">, </span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">excerpt_hash</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_6_1_5" class="named-paragraph-link"><span class="named-paragraph">Check the matched parameters for sanity</span><span class="named-paragraph-number">5.6.1.5</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">err</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_6_1_6" class="named-paragraph-link"><span class="named-paragraph">Record a successful parametrised match</span><span class="named-paragraph-number">5.6.1.6</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">saved_W</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5_6">&#167;5.6</a> (three times).</li></ul>
<p class="commentary firstcommentary"><a id="SP5_6_1_1" class="paragraph-anchor"></a><b>&#167;5.6.1.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Look through to see if there are phrase options at the end</span><span class="named-paragraph-number">5.6.1.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">id_body</span><span class="plain-syntax"> *</span><span class="identifier-syntax">idb</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ToPhraseFamily::meaning_as_phrase</span><span class="plain-syntax">(</span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">));</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PhraseOptions::allows_options</span><span class="plain-syntax">(</span><span class="identifier-syntax">idb</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">EXCERPT_PARSING</span><span class="plain-syntax">, </span><span class="string-syntax">"Looking for phrase options\n"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bl</span><span class="plain-syntax">=0, </span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">=</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)+1;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">Wordings::last_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">); </span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">) == </span><span class="identifier-syntax">COMMA_V</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">bl</span><span class="plain-syntax">==0)) {</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">ph_opt_W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Wordings::from</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">+1);</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Wordings::up_to</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">-1);</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">EXCERPT_PARSING</span><span class="plain-syntax">, </span><span class="string-syntax">"Found phrase options &lt;%W&gt;\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">ph_opt_W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            }</span>
<span class="plain-syntax">            </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_6_1_1_1" class="named-paragraph-link"><span class="named-paragraph">Maintain bracket level</span><span class="named-paragraph-number">5.6.1.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5_6_1">&#167;5.6.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_6_1_2" class="paragraph-anchor"></a><b>&#167;5.6.1.2. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">We're required to match a fixed word</span><span class="named-paragraph-number">5.6.1.2</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">this_word</span><span class="plain-syntax"> != </span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">)) { </span><span class="identifier-syntax">err</span><span class="plain-syntax">=</span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">; }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">this_word</span><span class="plain-syntax"> == </span><span class="identifier-syntax">word_to_suppress_in_phrases</span><span class="plain-syntax">) { </span><span class="identifier-syntax">err</span><span class="plain-syntax">=</span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">; }</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">++;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5_6_1">&#167;5.6.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_6_1_3" class="paragraph-anchor"></a><b>&#167;5.6.1.3. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">We're required to match a parameter at the excerpt's end</span><span class="named-paragraph-number">5.6.1.3</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">params_W</span><span class="plain-syntax">[</span><span class="identifier-syntax">t</span><span class="plain-syntax">++] = </span><span class="identifier-syntax">Wordings::from</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Wordings::last_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">) + </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5_6_1">&#167;5.6.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_6_1_4" class="paragraph-anchor"></a><b>&#167;5.6.1.4. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">We're required to match a parameter before the excerpt's end</span><span class="named-paragraph-number">5.6.1.4</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">fixed_words_at_end</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (; </span><span class="identifier-syntax">j</span><span class="plain-syntax">+1+</span><span class="identifier-syntax">fixed_words_at_end</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">no_tokens_to_match</span><span class="plain-syntax">; </span><span class="identifier-syntax">fixed_words_at_end</span><span class="plain-syntax">++)</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">em_tokens</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">+1+</span><span class="identifier-syntax">fixed_words_at_end</span><span class="plain-syntax">] == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">fixed_words_at_end</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">fixed_words_at_end</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">params_W</span><span class="plain-syntax">[</span><span class="identifier-syntax">t</span><span class="plain-syntax">++] =</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Wordings::new</span><span class="plain-syntax">(</span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">, </span><span class="identifier-syntax">Wordings::last_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">) - </span><span class="identifier-syntax">fixed_words_at_end</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Wordings::last_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">) - </span><span class="identifier-syntax">fixed_words_at_end</span><span class="plain-syntax"> + </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sentinel</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">em_tokens</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">+1];</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">bl_initial</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bl</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">start_word</span><span class="plain-syntax"> = </span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">err</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax"> &lt;= </span><span class="identifier-syntax">Wordings::last_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_6_1_1_1" class="named-paragraph-link"><span class="named-paragraph">Maintain bracket level</span><span class="named-paragraph-number">5.6.1.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">bl</span><span class="plain-syntax"> == </span><span class="identifier-syntax">bl_initial</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">start_word</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax">                (</span><span class="identifier-syntax">sentinel</span><span class="plain-syntax"> == </span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">))) { </span><span class="identifier-syntax">err</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">; }</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bl</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">bl_initial</span><span class="plain-syntax">) </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">params_W</span><span class="plain-syntax">[</span><span class="identifier-syntax">t</span><span class="plain-syntax">++] = </span><span class="identifier-syntax">Wordings::new</span><span class="plain-syntax">(</span><span class="identifier-syntax">start_word</span><span class="plain-syntax">, </span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">-1);</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5_6_1">&#167;5.6.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_6_1_5" class="paragraph-anchor"></a><b>&#167;5.6.1.5. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Check the matched parameters for sanity</span><span class="named-paragraph-number">5.6.1.5</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">x</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">j</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">no_tokens_to_match</span><span class="plain-syntax">) </span><span class="identifier-syntax">err</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax"> &lt;= </span><span class="identifier-syntax">Wordings::last_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) </span><span class="identifier-syntax">err</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">err</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">x</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">x</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">t</span><span class="plain-syntax">; </span><span class="identifier-syntax">x</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::empty</span><span class="plain-syntax">(</span><span class="identifier-syntax">params_W</span><span class="plain-syntax">[</span><span class="identifier-syntax">x</span><span class="plain-syntax">])) </span><span class="identifier-syntax">err</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">bl</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">LOOP_THROUGH_WORDING</span><span class="plain-syntax">(</span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">, </span><span class="identifier-syntax">params_W</span><span class="plain-syntax">[</span><span class="identifier-syntax">x</span><span class="plain-syntax">]) {</span>
<span class="plain-syntax">                    </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_6_1_1_1" class="named-paragraph-link"><span class="named-paragraph">Maintain bracket level</span><span class="named-paragraph-number">5.6.1.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">                    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bl</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">err</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                }</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bl</span><span class="plain-syntax"> != </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">err</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            }</span>
<span class="plain-syntax">        }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5_6_1">&#167;5.6.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_6_1_1_1" class="paragraph-anchor"></a><b>&#167;5.6.1.1.1. </b>Monitor bracket level:
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Maintain bracket level</span><span class="named-paragraph-number">5.6.1.1.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">) == </span><span class="identifier-syntax">OPENBRACKET_V</span><span class="plain-syntax">) ||</span>
<span class="plain-syntax">        (</span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">) == </span><span class="identifier-syntax">OPENBRACE_V</span><span class="plain-syntax">)) </span><span class="identifier-syntax">bl</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">) == </span><span class="identifier-syntax">CLOSEBRACKET_V</span><span class="plain-syntax">) ||</span>
<span class="plain-syntax">        (</span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">scan_pos</span><span class="plain-syntax">) == </span><span class="identifier-syntax">CLOSEBRACE_V</span><span class="plain-syntax">)) </span><span class="identifier-syntax">bl</span><span class="plain-syntax">--;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5_6_1_1">&#167;5.6.1.1</a>, <a href="2-pe.html#SP5_6_1_4">&#167;5.6.1.4</a> and <a href="2-pe.html#SP5_6_1_5">&#167;5.6.1.5</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_6_1_6" class="paragraph-anchor"></a><b>&#167;5.6.1.6. </b>A happy ending. We add the result to our linked list, annotating it with
nodes for the parameters and any phrase options.
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Record a successful parametrised match</span><span class="named-paragraph-number">5.6.1.6</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">last_param</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">this_result</span><span class="plain-syntax"> =</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Node::new_with_words</span><span class="plain-syntax">(</span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">meaning_code</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">Node::set_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">this_result</span><span class="plain-syntax">, </span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">));</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">this_result</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax"> = </span><span class="identifier-syntax">results</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">Node::set_score</span><span class="plain-syntax">(</span><span class="identifier-syntax">this_result</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::nonempty</span><span class="plain-syntax">(</span><span class="identifier-syntax">ph_opt_W</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">this_result</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::new_with_words</span><span class="plain-syntax">(</span><span class="identifier-syntax">UNKNOWN_NT</span><span class="plain-syntax">, </span><span class="identifier-syntax">ph_opt_W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Annotations::write_int</span><span class="plain-syntax">(</span><span class="identifier-syntax">this_result</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">is_phrase_option_ANNOT</span><span class="plain-syntax">, </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">last_param</span><span class="plain-syntax"> = </span><span class="identifier-syntax">this_result</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">x</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">x</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">t</span><span class="plain-syntax">; </span><span class="identifier-syntax">x</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p2</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">p2</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::new_with_words</span><span class="plain-syntax">(</span><span class="identifier-syntax">UNKNOWN_NT</span><span class="plain-syntax">, </span><span class="identifier-syntax">params_W</span><span class="plain-syntax">[</span><span class="identifier-syntax">x</span><span class="plain-syntax">]);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">last_param</span><span class="plain-syntax">) </span><span class="identifier-syntax">last_param</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p2</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">this_result</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p2</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">last_param</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p2</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">results</span><span class="plain-syntax"> = </span><span class="identifier-syntax">this_result</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5_6_1">&#167;5.6.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_7" class="paragraph-anchor"></a><b>&#167;5.7. Subset parsing mode.</b>In subset mode, each possible match is kept, and is assigned a numerical
score based purely on the number of words in the full description which were
missed out. This makes "door" a better match against "door" (0 words
missed out) than against "green door" (1 word missed out).
</p>

<p class="commentary">Note that a single word which also has a meaning as a number is never
matched. This is so that "11" (say) cannot be misinterpreted as an
abbreviated form of an object name like "Chamber 11".
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Enter subset parsing mode</span><span class="named-paragraph-number">5.7</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">Wordings::length</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">) == </span><span class="constant-syntax">1</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax">        ((</span><span class="identifier-syntax">Vocabulary::test_flags</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">), </span><span class="identifier-syntax">NUMBER_MC</span><span class="plain-syntax">)) != </span><span class="constant-syntax">0</span><span class="plain-syntax">))</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">goto</span><span class="plain-syntax"> </span><span class="identifier-syntax">SubsetFailed</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">j</span><span class="plain-syntax"> = -1, </span><span class="identifier-syntax">k</span><span class="plain-syntax"> = -1;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_THROUGH_WORDING</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">v</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">v</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Unidentified word when parsing"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">NTI::test_vocabulary</span><span class="plain-syntax">(</span><span class="identifier-syntax">v</span><span class="plain-syntax">, </span><span class="function-syntax">&lt;article&gt;</span><span class="plain-syntax">)) </span><span class="reserved-syntax">continue</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">v</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">means</span><span class="plain-syntax">.</span><span class="element-syntax">subset_list_length</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">goto</span><span class="plain-syntax"> </span><span class="identifier-syntax">SubsetFailed</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">v</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">means</span><span class="plain-syntax">.</span><span class="element-syntax">subset_list_length</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">j</span><span class="plain-syntax">) { </span><span class="identifier-syntax">j</span><span class="plain-syntax"> = </span><span class="identifier-syntax">v</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">means</span><span class="plain-syntax">.</span><span class="element-syntax">subset_list_length</span><span class="plain-syntax">; </span><span class="identifier-syntax">k</span><span class="plain-syntax"> = </span><span class="identifier-syntax">i</span><span class="plain-syntax">; }</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">k</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">v</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">k</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">v</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">means</span><span class="plain-syntax">.</span><span class="element-syntax">subset_list</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax">)</span>
<span class="plain-syntax">            </span><span class="named-paragraph-container code-font"><a href="2-pe.html#SP5_7_1" class="named-paragraph-link"><span class="named-paragraph">Try to match excerpt in subset parsing mode</span><span class="named-paragraph-number">5.7.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">SubsetFailed:</span><span class="plain-syntax"> ;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5">&#167;5</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_7_1" class="paragraph-anchor"></a><b>&#167;5.7.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Try to match excerpt in subset parsing mode</span><span class="named-paragraph-number">5.7.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">EXCERPT_MEANING_RELEVANT</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax">        ((</span><span class="identifier-syntax">hash</span><span class="plain-syntax"> &amp; </span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">excerpt_hash</span><span class="plain-syntax">) == </span><span class="identifier-syntax">hash</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="constant-syntax">EXAMINE_EXCERPT_MEANING_IN_DETAIL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::length</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">) &lt;= </span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">no_em_tokens</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">err</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pe.html#SP7" class="function-link"><span class="function-syntax">FromLexicon::parse_exactly</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">))) {</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">EXCERPT_PARSING</span><span class="plain-syntax">,</span>
<span class="plain-syntax">                    </span><span class="string-syntax">"Require exact matching of $M\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">));</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">err</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">no_em_tokens</span><span class="plain-syntax"> == </span><span class="identifier-syntax">Wordings::length</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">                    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">j</span><span class="plain-syntax">=0, </span><span class="identifier-syntax">k</span><span class="plain-syntax">=</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">), </span><span class="identifier-syntax">err</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                        </span><span class="identifier-syntax">j</span><span class="function-syntax">&lt;Node::get_meaning(p)-&gt;</span><span class="element-syntax">no_em_tokens</span><span class="plain-syntax">; </span><span class="identifier-syntax">j</span><span class="plain-syntax">++, </span><span class="identifier-syntax">k</span><span class="plain-syntax">++)</span>
<span class="plain-syntax">                        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">em_tokens</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">] != </span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">k</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">                            </span><span class="identifier-syntax">err</span><span class="plain-syntax">=</span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                        }</span>
<span class="plain-syntax">                }</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">goto</span><span class="plain-syntax"> </span><span class="identifier-syntax">SubsetMatchDecided</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            }</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">LOOP_THROUGH_WORDING</span><span class="plain-syntax">(</span><span class="identifier-syntax">k</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">err</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">j</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">j</span><span class="function-syntax">&lt;Node::get_meaning(p)-&gt;</span><span class="element-syntax">no_em_tokens</span><span class="plain-syntax">; </span><span class="identifier-syntax">j</span><span class="plain-syntax">++)</span>
<span class="plain-syntax">                    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">em_tokens</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">] == </span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">k</span><span class="plain-syntax">)) </span><span class="identifier-syntax">err</span><span class="plain-syntax">=</span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">err</span><span class="plain-syntax">) </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            }</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">SubsetMatchDecided:</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">err</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">excerpt_meaning</span><span class="plain-syntax"> *</span><span class="identifier-syntax">em</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::get_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">);</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">results</span><span class="plain-syntax"> = </span><a href="2-pe.html#SP8" class="function-link"><span class="function-syntax">FromLexicon::result</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">em</span><span class="plain-syntax">,</span>
<span class="plain-syntax">                    </span><span class="constant-syntax">100</span><span class="plain-syntax">-((</span><span class="identifier-syntax">em</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_em_tokens</span><span class="plain-syntax">) - (</span><span class="identifier-syntax">Wordings::length</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)-1)),</span>
<span class="plain-syntax">                    </span><span class="identifier-syntax">results</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            }</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pe.html#SP5_7">&#167;5.7</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. </b>Inform uses the callback here simply to disallow inexact parsing of <span class="extract"><span class="extract-syntax">NOUN_NT</span></span>
excerpts when the use option "unabbreviated object names" is set.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">FromLexicon::parse_exactly</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">FromLexicon::parse_exactly</span></span>:<br/><a href="2-pe.html#SP5_7_1">&#167;5.7.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">excerpt_meaning</span><span class="plain-syntax"> *</span><span class="identifier-syntax">em</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">PARSE_EXACTLY_LEXICON_CALLBACK</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">PARSE_EXACTLY_LEXICON_CALLBACK</span><span class="plain-syntax">(</span><span class="identifier-syntax">em</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifndef</span><span class="plain-syntax"> </span><span class="identifier-syntax">PARSE_EXACTLY_LEXICON_CALLBACK</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">em</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">meaning_code</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NOUN_MC</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>&#167;8. </b>The following adds a result to the list already formed, and returns the list
as extended by one.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="function-syntax">FromLexicon::result</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">FromLexicon::result</span></span>:<br/><a href="2-pe.html#SP5_4_1">&#167;5.4.1</a>, <a href="2-pe.html#SP5_5">&#167;5.5</a>, <a href="2-pe.html#SP5_7_1">&#167;5.7.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">excerpt_meaning</span><span class="plain-syntax"> *</span><span class="identifier-syntax">em</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">score</span><span class="plain-syntax">, </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">list</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">this_result</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">PN_FROM_EM_LEXICON_CALLBACK</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">this_result</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PN_FROM_EM_LEXICON_CALLBACK</span><span class="plain-syntax">(</span><span class="identifier-syntax">em</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifndef</span><span class="plain-syntax"> </span><span class="identifier-syntax">PN_FROM_EM_LEXICON_CALLBACK</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">VALID_POINTER_parse_node</span><span class="plain-syntax">(</span><a href="1-lxc.html#SP2" class="function-link"><span class="function-syntax">Lexicon::get_data</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">em</span><span class="plain-syntax">))) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">val</span><span class="plain-syntax"> = </span><span class="identifier-syntax">RETRIEVE_POINTER_parse_node</span><span class="plain-syntax">(</span><a href="1-lxc.html#SP2" class="function-link"><span class="function-syntax">Lexicon::get_data</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">em</span><span class="plain-syntax">));</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">this_result</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::new</span><span class="plain-syntax">(</span><span class="identifier-syntax">INVALID_NT</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Node::copy</span><span class="plain-syntax">(</span><span class="identifier-syntax">this_result</span><span class="plain-syntax">, </span><span class="identifier-syntax">val</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">this_result</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::new</span><span class="plain-syntax">(</span><span class="identifier-syntax">em</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">meaning_code</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Node::set_meaning</span><span class="plain-syntax">(</span><span class="identifier-syntax">this_result</span><span class="plain-syntax">, </span><span class="identifier-syntax">em</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">this_result</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax"> = </span><span class="identifier-syntax">list</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">Node::set_score</span><span class="plain-syntax">(</span><span class="identifier-syntax">this_result</span><span class="plain-syntax">, </span><span class="identifier-syntax">score</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">this_result</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>

<span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="function-syntax">FromLexicon::retrieve_parse_node</span><span class="plain-syntax">(</span><span class="reserved-syntax">excerpt_meaning</span><span class="plain-syntax"> *</span><span class="identifier-syntax">em</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">em</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">PN_FROM_EM_LEXICON_CALLBACK</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">PN_FROM_EM_LEXICON_CALLBACK</span><span class="plain-syntax">(</span><span class="identifier-syntax">em</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifndef</span><span class="plain-syntax"> </span><span class="identifier-syntax">PN_FROM_EM_LEXICON_CALLBACK</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">RETRIEVE_POINTER_parse_node</span><span class="plain-syntax">(</span><a href="1-lxc.html#SP2" class="function-link"><span class="function-syntax">Lexicon::get_data</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">em</span><span class="plain-syntax">));</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>&#167;9. Monitoring the efficiency of the parser.</b>The present value of these statistics when the lexicon is used in making a
typical Inform story can be read off in <a href="../inform7/M-pm.html" class="internal">Performance Metrics (in inform7)</a>.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">FromLexicon::statistics</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Size of lexicon: %d excerpt meanings\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">NUMBER_CREATED</span><span class="plain-syntax">(</span><span class="reserved-syntax">excerpt_meaning</span><span class="plain-syntax">));</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sve</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, *</span><span class="identifier-syntax">eve</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, *</span><span class="identifier-syntax">mve</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, *</span><span class="identifier-syntax">subve</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">lsl</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">lel</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">lml</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">lsubl</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">nsl</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">nel</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">nml</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">nsubl</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">m</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">n</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">lexer_wordcount</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ve</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">vocabulary_lexicon_data</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ld</span><span class="plain-syntax"> = &amp;(</span><span class="identifier-syntax">ve</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">means</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">ld</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">ld</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">scanned_already</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">m</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">ld</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">scanned_already</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">sl</span><span class="plain-syntax"> = </span><a href="2-pe.html#SP9" class="function-link"><span class="function-syntax">FromLexicon::len</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">ld</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">start_list</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">el</span><span class="plain-syntax"> = </span><a href="2-pe.html#SP9" class="function-link"><span class="function-syntax">FromLexicon::len</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">ld</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">end_list</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">ml</span><span class="plain-syntax"> = </span><a href="2-pe.html#SP9" class="function-link"><span class="function-syntax">FromLexicon::len</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">ld</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">middle_list</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">subl</span><span class="plain-syntax"> = </span><a href="2-pe.html#SP9" class="function-link"><span class="function-syntax">FromLexicon::len</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">ld</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">subset_list</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">sl</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">nsl</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">el</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">nel</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ml</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">nml</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">subl</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">nsubl</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">sl</span><span class="plain-syntax"> + </span><span class="identifier-syntax">el</span><span class="plain-syntax"> + </span><span class="identifier-syntax">ml</span><span class="plain-syntax"> + </span><span class="identifier-syntax">subl</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">n</span><span class="plain-syntax">++;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">sl</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">lsl</span><span class="plain-syntax">) { </span><span class="identifier-syntax">lsl</span><span class="plain-syntax"> = </span><span class="identifier-syntax">sl</span><span class="plain-syntax">; </span><span class="identifier-syntax">sve</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ve</span><span class="plain-syntax">; }</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">el</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">lel</span><span class="plain-syntax">) { </span><span class="identifier-syntax">lel</span><span class="plain-syntax"> = </span><span class="identifier-syntax">el</span><span class="plain-syntax">; </span><span class="identifier-syntax">eve</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ve</span><span class="plain-syntax">; }</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ml</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">lml</span><span class="plain-syntax">) { </span><span class="identifier-syntax">lml</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ml</span><span class="plain-syntax">; </span><span class="identifier-syntax">mve</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ve</span><span class="plain-syntax">; }</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">subl</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">lsubl</span><span class="plain-syntax">) { </span><span class="identifier-syntax">lsubl</span><span class="plain-syntax"> = </span><span class="identifier-syntax">subl</span><span class="plain-syntax">; </span><span class="identifier-syntax">subve</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ve</span><span class="plain-syntax">; }</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  Stored among %d words out of total vocabulary of %d\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">n</span><span class="plain-syntax">, </span><span class="identifier-syntax">m</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">nsl</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  %d words have a start list: longest belongs to %V (with %d meanings)\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">nsl</span><span class="plain-syntax">, </span><span class="identifier-syntax">sve</span><span class="plain-syntax">, </span><span class="identifier-syntax">lsl</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">nel</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  %d words have an end list: longest belongs to %V (with %d meanings)\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">nel</span><span class="plain-syntax">, </span><span class="identifier-syntax">eve</span><span class="plain-syntax">, </span><span class="identifier-syntax">lel</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">nml</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  %d words have a middle list: longest belongs to %V (with %d meanings)\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">nml</span><span class="plain-syntax">, </span><span class="identifier-syntax">mve</span><span class="plain-syntax">, </span><span class="identifier-syntax">lml</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">nsubl</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  %d words have a subset list: longest belongs to %V (with %d meanings)\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">nsubl</span><span class="plain-syntax">, </span><span class="identifier-syntax">subve</span><span class="plain-syntax">, </span><span class="identifier-syntax">lsubl</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"\n"</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Number of attempts to retrieve: %d\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">no_calls_to_parse_excerpt</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  of which unsuccessful: %d\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">no_calls_to_parse_excerpt</span><span class="plain-syntax"> - </span><span class="identifier-syntax">no_successful_calls_to_parse_excerpt</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  of which successful: %d\n\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">no_successful_calls_to_parse_excerpt</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Total attempts to match against excerpt meanings: %d\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">no_meanings_tried</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  of which, total with incorrect hash codes: %d\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">no_meanings_tried</span><span class="plain-syntax"> - </span><span class="identifier-syntax">no_meanings_tried_in_detail</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  of which, total with correct hash codes: %d\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">no_meanings_tried_in_detail</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  of which, total which matched: %d\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">no_matched_ems</span><span class="plain-syntax">);</span>


<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Log::aspect_switched_on</span><span class="plain-syntax">(</span><span class="constant-syntax">EXCERPT_MEANINGS_DA</span><span class="plain-syntax">)) </span><a href="2-em.html#SP6" class="function-link"><span class="function-syntax">ExcerptMeanings::log_all</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax">}</span>

<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">FromLexicon::len</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">N</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">N</span><span class="plain-syntax">++; </span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">N</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
    <ul class="progressbar"><li class="progressprev"><a href="2-em.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-lm.html">1</a></li><li class="progresscurrentchapter">2</li><li class="progresssection"><a href="2-em.html">em</a></li><li class="progresscurrent">pe</li><li class="progressnextoff">&#10095;</li></ul></div>
</nav><!-- End of weave -->

		</main>
	</body>
</html>

